#include <cstdlib>

#include "ilistenapplication.h"

#define STRINGIFY(x) XSTRINGIFY(x)
#define XSTRINGIFY(x) #x

iListenApplication::iListenApplication()
    :m_login_response_cb(nullptr), m_object_datas_cb(nullptr), m_pong_cb(nullptr)
{
    // setup the parser
    m_streamHandler = new IVEFStreamHandler(&m_parser);
    // and the handles
    connect( &m_parser, SIGNAL( signalMSG_IVEF(ivef::MSG_IVEF)), this, SLOT( handleMsgIvef(ivef::MSG_IVEF) ));
    connect( &m_parser, SIGNAL( signalError(QString)), this, SLOT( handleError(QString) ));
    connect( &m_parser, SIGNAL( signalWarning(QString)), this, SLOT( handleError(QString) ));
    connect( &m_parser, SIGNAL( signalValidationError(QString)), this, SLOT( handleError(QString) ));

    m_ping_timer = new QTimer();
    connect(m_ping_timer, SIGNAL(timeout()), m_streamHandler, SLOT(ping()));
}

void iListenApplication::setNetErrorCb(netErrorCallback cb)
{
    m_streamHandler->setnetErrorCallback(cb);
}

void iListenApplication::setLoginResponseCb(LoginResponseCallback cb)
{
    m_login_response_cb = cb;
}

void iListenApplication::setObjectDatasCb(ObjectDatasCallback cb)
{
    m_object_datas_cb = cb;
}

void iListenApplication::setPongCb(PongCallback cb)
{
    m_pong_cb = cb;
}

void iListenApplication::StartPing(bool ping)
{
    if (ping)
    {
        m_ping_timer->start(1000);
    }
    else
    {
        m_ping_timer->stop();
    }
}

void iListenApplication::SendObjectDatas(const ivef::ObjectDatas &datas)
{
    m_streamHandler->sendObjectDatas(datas);
}

void iListenApplication::connectToServer(QString host, int port, QString user, QString password,
    QString logFileName, bool slipstream, bool statistics)
{
    m_host = host;
    m_port = port;
    m_user = user;
    m_password = password;
    m_logFileName = logFileName;
    m_slipstream = slipstream;
    m_statistics = statistics;

    // startup timer, to allow the event loop to start
    QTimer *timer = new QTimer(0); // we leak one timer here, is acceptable
    timer->setInterval(100);
    timer->setSingleShot(true);
    connect(timer, SIGNAL(timeout()), this, SLOT(startConnect()));
    timer->start();
}

void iListenApplication::startConnect()
{
    m_streamHandler->connectToServer(m_host, m_port, m_user, m_password, m_logFileName, m_slipstream, m_statistics);
}

void iListenApplication::handleMsgIvef( ivef::MSG_IVEF obj )
{
    if (obj.getBody().hasObjectDatas())
    {
        if (m_object_datas_cb != nullptr)
        {
            m_object_datas_cb(obj.getBody().getObjectDatas());
        }
    }

    if (obj.getBody().hasLoginResponse())
    {
        if (m_login_response_cb != nullptr)
        {
            m_login_response_cb(obj.getBody().getLoginResponse());
        }
    }

    if (obj.getBody().hasPong())
    {
        if (m_pong_cb != nullptr)
        {
            m_pong_cb(obj.getBody().getPong());
        }
    }
}

void iListenApplication::handleError( QString errorStr )
{
    std::cerr << errorStr.toUtf8().data() << std::endl;
}
